import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author GAX
 * @date 2025-09-03
 */
public class SaleTicketLock {
    public static void main(String[] args) {
        Ticket02 ticket02 = new Ticket02();

        // 创建线程
        new Thread(() -> {
            for (int i = 0; i < 50; i++) {
                // 线程去操作共享资源
                ticket02.sale();
            }
        },"线程 A").start();

        new Thread(() -> {
            for (int i = 0; i < 50; i++) {
                // 线程去操作共享资源
                ticket02.sale();
            }
        },"线程 B").start();

        new Thread(() -> {
            for (int i = 0; i < 50; i++) {
                // 线程去操作共享资源
                ticket02.sale();
            }
        },"线程 C").start();
    }
}

// ① 创建共享资源类
class Ticket02 {
    private int number = 50;

    // 创建一个可重入锁（ReentrantLock）实例，用于保护共享资源。
    // ReentrantLock 是 Lock 接口的一个常见实现。
    private final Lock lock = new ReentrantLock(true); // 初始化为公平锁

    // ② 操作 --- 售票方法
    public void sale() {
        // 使用 lock() 和 unlock() 来确保同一时间只有一个线程使用共享资源。
        // 获取锁：lock() 是阻塞式方法，如果锁已经被其他线程持有，当前线程会一直等待直到获取锁。
        lock.lock();
        try {
            if (number > 0) {
                System.out.println(Thread.currentThread().getName() + "\t"
                        +"卖出第：" + (number --) + "\t"
                        + "还剩下：" + number);
            }
        } finally {
            // 释放锁：unlock()，这一步至关重要，如果忘记解锁，其他线程将永远无法获取锁，导致死锁。
            lock.unlock();
        }
    }
}
